package com.lai.hospital.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lai.hospital.dao.AppointmentDao;
import com.lai.hospital.dao.DepartmentDao;
import com.lai.hospital.dao.DoctorDao;
import com.lai.hospital.dao.DoctorScheduleDao;
import com.lai.hospital.dto.AppointmentDTO;
import com.lai.hospital.dto.ConfirmAppointmentDTO;
import com.lai.hospital.dto.MedicalInfoDTO;
import com.lai.hospital.entity.Appointment;
import com.lai.hospital.entity.Doctor;
import com.lai.hospital.entity.DoctorSchedule;
import com.lai.hospital.entity.Patient;
import com.lai.hospital.enums.AppointmentStatusEnum;
import com.lai.hospital.exception.BizException;
import com.lai.hospital.service.AppointmentService;
import com.lai.hospital.service.PatientService;
import com.lai.hospital.service.UserPatientService;
import com.lai.hospital.utils.PageUtils;
import com.lai.hospital.utils.UserUtils;
import com.lai.hospital.vo.AppointmentVO;
import com.lai.hospital.vo.ConditionVO;
import com.lai.hospital.vo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author : lai
 * @version V1.0
 * @Project: hospital-springboot
 * @Package com.lai.hospital.service.impl
 * @Description: 预约服务
 * @date Date : 2022年11月27日 23:44
 */
@Service
public class AppointmentServiceImpl extends ServiceImpl<AppointmentDao, Appointment> implements AppointmentService {

    @Autowired
    private AppointmentDao appointmentDao;


    @Autowired
    private DoctorDao doctorDao;

    @Autowired
    private DoctorScheduleDao doctorScheduleDao;

    @Autowired
    private PatientService patientService;

    @Override
    public PageResult<AppointmentDTO> listAppointment(ConditionVO conditionVO) {
        Integer count;
        Date startTime = null;
        Date endTime = null;
        if (StringUtils.isNotBlank(conditionVO.getStartTime())) {
            startTime = DateUtil.parse(conditionVO.getStartTime(), "yyyy-MM-dd");
        }
        if (StringUtils.isNotBlank(conditionVO.getEndTime())) {
            endTime = DateUtil.parse(conditionVO.getEndTime(), "yyyy-MM-dd");
        }
        List<AppointmentDTO> appointmentDTOList = appointmentDao.listAppointment(PageUtils.getLimitCurrent(), PageUtils.getSize(), conditionVO, startTime, endTime);
        List<AppointmentDTO> appointmentList = appointmentDTOList.stream().map(item -> {
            item.setRegistrationFee(new BigDecimal(18.0));
            item.setRegistrationType("专家号");
            return item;
        }).collect(Collectors.toList());
        if (StringUtils.isNotBlank(conditionVO.getStartTime()) || StringUtils.isNotBlank(conditionVO.getEndTime())
                || StringUtils.isNotBlank(conditionVO.getKeywords()) || Objects.nonNull(conditionVO.getDepartmentId())
                || Objects.nonNull(conditionVO.getStatus())) {
            count = appointmentDTOList.size();
        } else {
            count = appointmentDao.selectCount(null);
        }
        return new PageResult<>(appointmentList, count);
    }

    @Override
    public PageResult<AppointmentDTO> listAppointmentByDoctorId(ConditionVO conditionVO) {
        Integer count;
        Date startTime = null;
        Date endTime = null;
        if (StringUtils.isNotBlank(conditionVO.getStartTime())) {
            startTime = DateUtil.parse(conditionVO.getStartTime(), "yyyy-MM-dd");
        }
        if (StringUtils.isNotBlank(conditionVO.getEndTime())) {
            endTime = DateUtil.parse(conditionVO.getEndTime(), "yyyy-MM-dd");
        }
        Doctor doctor = doctorDao.selectOne(new LambdaQueryWrapper<Doctor>()
                .eq(Doctor::getUserAuthId, UserUtils.getLoginUser().getId()));
        List<AppointmentDTO> appointmentDTOList = appointmentDao.listAppointmentByDoctorId(PageUtils.getLimitCurrent(), PageUtils.getSize(), conditionVO, startTime, endTime,doctor.getId());
        List<AppointmentDTO> appointmentList = appointmentDTOList.stream().map(item -> {
            item.setRegistrationFee(new BigDecimal(18.0));
            item.setRegistrationType("专家号");
            return item;
        }).collect(Collectors.toList());
        if (StringUtils.isNotBlank(conditionVO.getStartTime()) || StringUtils.isNotBlank(conditionVO.getEndTime())
                || StringUtils.isNotBlank(conditionVO.getKeywords()) || Objects.nonNull(conditionVO.getStatus())) {
            count = appointmentDTOList.size();
        } else {
            count = appointmentDao.selectCount(new LambdaQueryWrapper<Appointment>()
                    .eq(Appointment::getDoctorId,doctor.getId()));
        }
        return new PageResult<>(appointmentList, count);
    }

    @Override
    public void deleteAppointment(Integer id) {
        appointmentDao.deleteById(id);
    }

    @Override
    public List<MedicalInfoDTO> listAppointmentByPatientId(Integer patientId) {
        List<MedicalInfoDTO> medicalInfoDTOS = appointmentDao.listAppointmentByPatientId(UserUtils.getLoginUser().getUserInfoId(), patientId);
        if (medicalInfoDTOS.size() > 0 || Objects.nonNull(medicalInfoDTOS)) {
            return medicalInfoDTOS.stream().map(item -> {
                        String timeQuantum = item.getTimeQuantum() == 1 ? "上午" : "下午";
                        item.setAppointmentTime(item.getAppointmentTime().split(" ")[0] + " " + timeQuantum);
                        return item;
                    }).collect(Collectors.toList());
        }
        return medicalInfoDTOS;

    }

    @Override
    public List<AppointmentDTO> listAppointmentByUserId(ConditionVO conditionVO) {
        return appointmentDao.listAppointmentByUserId(UserUtils.getLoginUser().getUserInfoId(), conditionVO);
    }

    @Override
    public void cancelAppointment(Integer id) {
        Appointment appointment = Appointment.builder()
                .id(id)
                .appointmentStatus(AppointmentStatusEnum.CANCEL.getStatus())
                .build();
        appointmentDao.updateById(appointment);
        Appointment appointmentById = appointmentDao.selectById(id);
        //日开始时间
        DateTime beginOfDay = DateUtil.beginOfDay(appointmentById.getAppointmentTime());
        //日结束时间
        DateTime endOfDay = DateUtil.endOfDay(appointmentById.getAppointmentTime());
        //查询出 日开始时间 日结束时间之间得医生排班信息
        DoctorSchedule doctorSchedule = doctorScheduleDao.selectOne(new LambdaQueryWrapper<DoctorSchedule>()
                .eq(DoctorSchedule::getDoctorId, appointmentById.getDoctorId())
                .eq(DoctorSchedule::getDepartmentId, appointmentById.getDepartmentId())
                .eq(DoctorSchedule::getTimeQuantum, appointmentById.getTimeQuantum())
                .gt(DoctorSchedule::getScheduleTime, beginOfDay)
                .lt(DoctorSchedule::getScheduleTime, endOfDay));
        doctorSchedule.setNumberSource(doctorSchedule.getNumberSource() + 1);
        //让排班号源+1
        doctorScheduleDao.updateById(doctorSchedule);
    }

    @Override
    @Transactional(rollbackFor = BizException.class)
    public AppointmentVO saveAppointment(AppointmentVO appointmentVO) {
        Appointment appointment = Appointment.builder()
                .userId(UserUtils.getLoginUser().getUserInfoId())
                .patientId(appointmentVO.getPatientId())
                .hospitalId(appointmentVO.getHospitalId())
                .departmentId(appointmentVO.getDepartmentId())
                .doctorId(appointmentVO.getDoctorId())
                .appointmentTime(appointmentVO.getAppointmentTime())
                .timeQuantum(appointmentVO.getTimeQuantum())
                .appointmentStatus(AppointmentStatusEnum.WAITE.getStatus())
                .build();
        appointmentDao.insert(appointment);
//        String appointmentTime = DateUtil.format(appointment.getAppointmentTime(), "yyyy-MM-dd");
//        Appointment appointmentOne = appointmentDao.selectOne(new LambdaQueryWrapper<Appointment>()
//                .eq(Appointment::getUserId, appointment.getUserId())
//                .eq(Appointment::getPatientId, appointment.getPatientId())
//                .eq(Appointment::getDepartmentId, appointment.getDepartmentId())
//                .eq(Appointment::getDoctorId, appointment.getDoctorId())
//                .eq(Appointment::getAppointmentTime, appointmentTime)
//                .eq(Appointment::getTimeQuantum, appointment.getTimeQuantum())
//                .eq(Appointment::getAppointmentStatus, AppointmentStatusEnum.WAITE.getStatus()));
//        appointmentVO.setId(appointmentOne.getId());
//        appointmentVO.setAppointmentStatus(appointmentOne.getAppointmentStatus());
        return appointmentVO;
    }

    @Override
    public AppointmentDTO getAppointmentById(Integer id) {
        return appointmentDao.getAppointmentById(id);
    }


}
